#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

void func(void);
jmp_buf place;

unsigned long int mangle64(unsigned long int addr)
{
    unsigned long int ret;
    asm volatile("xorq %%fs:0x30,%0\n"

        "rolq $0x11,%0\n"
        : "=r" (ret)
        : "0" (addr));

    return ret;
}


unsigned long int demangle64(unsigned long int addr)
{
    unsigned long int ret;
    asm volatile("rorq $0x11,%0\n"

        "xorq %%fs:0x30,%0\n"
        : "=r" (ret)
        : "0" (addr));

    return ret;
}


main(){
        int retval;

      // _jmp_buf_tag tag;
        /*
         * First call returns 0,
         * a later longjmp will return non-zero.
         */
	 
        if(setjmp(place) != 0){
	
		  long int tem = demangle64(place->__jmpbuf[7]);
                printf("Returned using longjmp:%x\n",tem);

                exit(EXIT_SUCCESS);
        }

        
         /* This call will never return - it
         * 'jumps' back above.
         */
          
	   func();
        printf("What! func returned!\n");
}

void
func(void){
      /*
       * Return to main.
       * Looks like a second return from setjmp,
       * returning 4!
       */
      printf("What! longjmp called!\n");       

      longjmp(place, 4);
	
      printf("What! longjmp returned!\n");
}

